from cmd import Cmd
from action import Action
import os
import sys


class Client(Cmd):

    prompt = 'DT-chain> '
    intro = 'Welcome to DT-chain!'

    def __init__(self):
        Cmd.__init__(self)
        self.action = Action()
        self.help_dict = {
            'start': 'To start service.',
            'get_local_node_info': 'To get local node information.',
            'get_blocks': 'To fuzzy query, and this is the most powerful command.',
            'upload': 'To release a block of upload type.',
            'request': 'To release a block of request type.',
            'share': 'To release a block of share type.',
            'evaluate': 'To release a block of evaluate type.',
            'unpack': 'To unpack the data bundle and get the data.',
            'create_local_node': 'To create the local node.',
            'delete_local_node': 'To delete the local node.',
            'create_genesis_block': 'To create the genesis block.',
            'get_xtype_num': 'To know the number of blocks of a certain type.',
            'get_cur_height': 'To know current last height.',
            'get_xheight_cnrp': 'To get the GLOBAL-CNRP of certain height.',
            'get_xheight_block': 'To get the information of block by certain height.',
            'get_local_cnrp': 'To get the LOCAL-CNRP of local node.',
            'exit': 'To exit the program.'
        }

    # def preloop(self):
    #     pass

    # def postloop(self):
    #     pass

    # def precmd(self, line):
    #     pass

    # def postcmd(self, stop, line):
    #     pass

    # --------------------------------------------

    def do_start(self, arg):
        state = self.action.server_start()
        if state == 0:
            print('OK: Service is started.')
        else:
            print('Wrong: No service.')

    def help_start(self):
        print('Description: ', self.help_dict['start'])
        print('Parameters : ', 'none')

    def do_get_local_node_info(self, arg):
        state, info = self.action.get_local_node_info()
        if state == 0:
            print('-'*20 + '| Local Node Info |' + '-'*20)
            for k in info:
                print(k + ':')
                print(info[k])
                print('-'*40)
        else:
            print('Wrong: ', state, info)

    def help_get_local_node_info(self):
        print('Description: ', self.help_dict['get_local_node_info'])
        print('Parameters : ', 'none')

    def do_get_blocks(self, arg):
        arg_list = arg.split(' ')
        condition = {}
        for i in range(0, len(arg_list), 2):
            s = arg_list[i]
            if s == 'tx_type':
                condition[s] = arg_list[i + 1].split(',')
                continue
            condition[s] = arg_list[i+1]
        query_res = self.action.find_blocks(condition)
        print('-' * 20 + '| Query Result |' + '-' * 20)
        i = 0
        for block in query_res:
            print(i, ':', block.serialize())
            print('-' * 40)
            i += 1

    def help_get_blocks(self):
        print('Description: ', self.help_dict['get_blocks'])
        print('Parameters : ', '[query_field] [value] [query_field] [value] ...')
        print('Example    : ', 'tx_type upload,request,share node_address abc123')

    def do_upload(self, arg):
        arg_list = arg.split(' ', 1)
        state, info = self.action.upload(arg_list[0], arg_list[1])
        if state == 0:
            print('OK: Release success. The tx_id is: ' + info)
        else:
            print('Wrong: ', state, info)

    def help_upload(self):
        print('Description: ', self.help_dict['upload'])
        print('Parameters : ', '[data] [data_description]')
        print('Example    : ', '123nihao This is a test.')

    def do_request(self, arg):
        state, info = self.action.request(arg)
        if state == 0:
            print('OK: Release success. The tx_id is: ' + info)
        else:
            print('Wrong: ', state, info)

    def help_request(self):
        print('Description: ', self.help_dict['request'])
        print('Parameters : ', '[upload_tx_id]')

    def do_share(self, arg):
        state, info = self.action.share(arg)
        if state == 0:
            print('OK: Release success. The tx_id is: ' + info)
        else:
            print('Wrong: ', state, info)

    def help_share(self):
        print('Description: ', self.help_dict['share'])
        print('Parameters : ', '[request_tx_id]')

    def do_evaluate(self, arg):
        arg_list = arg.split(' ')
        state, info = self.action.evaluate(arg_list[0], arg_list[1])
        if state == 0:
            print('OK: Release success. The tx_id is: ' + info)
        else:
            print('Wrong: ', state, info)

    def help_evaluate(self):
        print('Description: ', self.help_dict['evaluate'])
        print('Parameters : ', '[share_tx_id] [data_score]')
        print('Example    : ', 'qwerty123uiop 10')

    def do_unpack(self, arg):
        state, info = self.action.unpack_data(arg)
        if state == 0:
            data = info.serialize()
            print('-' * 20 + '| Data Bundle Info |' + '-' * 20)
            for k in data:
                print(k + ':')
                print(data[k])
                print('-' * 40)
        else:
            print('Wrong: ', state, info)

    def help_unpack(self):
        print('Description: ', self.help_dict['unpack'])
        print('Parameters : ', '[share_tx_id]')

    def do_create_local_node(self, arg):
        state, info = self.action.create_local_node()
        if state == 0:
            print('OK: Create success. The local node address is: ' + info)
        else:
            print('Wrong: ', state, info)

    def help_create_local_node(self):
        print('Description: ', self.help_dict['create_local_node'])
        print('Parameters : ', 'none')

    def do_delete_local_node(self, arg):
        state, info = self.action.create_local_node()
        if state == 0:
            print('OK: Delete success.')
        else:
            print('Wrong: ', state, info)

    def help_delete_local_node(self):
        print('Description: ', self.help_dict['delete_local_node'])
        print('Parameters : ', 'none')

    def do_create_genesis_block(self, arg):
        state, info = self.action.create_genesis_block()
        if state == 0:
            print('OK: Create success.')
        else:
            print('Wrong: ', state, info)

    def help_create_genesis_block(self):
        print('Description: ', self.help_dict['create_genesis_block'])
        print('Parameters : ', 'none')

    def do_get_xtype_num(self, arg):
        state, info = self.action.get_xtype_num(arg)
        if state == 0:
            print('The number of ' + arg + 'blocks: ', info)
        else:
            print('Wrong: ', state, info)

    def help_get_xtype_num(self):
        print('Description: ', self.help_dict['get_xtype_num'])
        print('Parameters : ', '[tx_type]')

    def do_get_cur_height(self, arg):
        state, info = self.action.get_cur_height()
        if state == 0:
            print('Current height: ', info)
        else:
            print('Wrong: ', state, info)

    def help_get_cur_height(self):
        print('Description: ', self.help_dict['get_cur_height'])
        print('Parameters : ', '[height - support negative query]')
        print('Example    : ', '-1')

    def do_get_xheight_cnrp(self, arg):
        height = int(arg)
        if height < 0:
            height = self.action.get_cur_height()[1] + height + 1
        state, info = self.action.get_global_cnrp_by_height(height)
        if state == 0:
            print('-' * 20 + '| Global CNRP Dict Info -' + str(height) + ' |' + '-' * 20)
            for k in info:
                print(k + ':')
                print(info[k])
                print('-' * 40)
        else:
            print('Wrong: ', state, info)

    def help_get_xheight_cnrp(self):
        print('Description: ', self.help_dict['get_xheight_cnrp'])
        print('Parameters : ', '[height - support negative query]')
        print('Example    : ', '-1')

    def do_get_xheight_block(self, arg):
        height = int(arg)
        if height < 0:
            height = self.action.get_cur_height()[1] + height + 1
        state, info = self.action.get_block_by_height(height)
        if state == 0:
            block = info.serialize()
            print('-' * 20 + '| Last Block Info |' + '-' * 20)
            block.serialize()
            print('-'*40)
        else:
            print('Wrong: ', state, info)

    def help_get_xheight_block(self):
        print('Description: ', self.help_dict['get_xheight_block'])
        print('Parameters : ', '[height - support negative query]')
        print('Example    : ', '-1')

    def do_get_local_cnrp(self, arg):
        state, info = self.action.get_local_cnrp_dict()
        if state == 0:
            print('-' * 20 + '| Local CNRP Dict Info |' + '-' * 20)
            for k in info:
                print(k + ':')
                print(info[k])
                print('-' * 40)
        else:
            print('Wrong: ', state, info)

    def help_get_local_cnrp(self):
        print('Description: ', self.help_dict['get_local_cnrp'])
        print('Parameters : ', 'none')

    def do_exit(self, arg):
        print('The program has exited.')
        return True

    def help_exit(self):
        print('Description: ', self.help_dict['exit'])
        print('Parameters : ', 'none')

    # -----------------------------------

    def emptyline(self):
        print("Input 'help [command]' to get more detail about command as follows:")
        print('-' * 20 + '| Command List |' + '-' * 20)
        help_dict = self.help_dict
        for k in help_dict:
            command_name = '%20s' % k
            print(command_name + ': ' + help_dict[k])
        print('-' * 56)

    def default(self, arg):
        print('Wrong command.')
        self.emptyline()


if __name__ == '__main__':
    client = Client()
    client.cmdloop()

    # try:
    #     # os.system('cls')
    #     client = Client()
    #     client.cmdloop()
    # except:
    #     exit()

